"""Main network service integration module."""

import asyncio
import logging
import signal
import sys
from typing import Optional

from .monitor import NetworkMonitor
from .ble_manager import BLEServiceManager
from .state_machine import NetworkStateMachine
from .config import NetworkConfig

# Import BLE module if available
try:
    from ..ble.gatt_server import BLEGATTServer
except ImportError:
    BLEGATTServer = None
    
logger = logging.getLogger(__name__)


class NetworkService:
    """Main network service coordinator."""
    
    def __init__(self, config_path: Optional[str] = None):
        """
        Initialize network service.
        
        Args:
            config_path: Path to configuration file
        """
        # Load configuration
        self.config = NetworkConfig(config_path)
        self._setup_logging()
        
        # Initialize components
        self.network_monitor = None
        self.ble_manager = None
        self.state_machine = None
        self.ble_server = None
        
        self._running = False
        self._shutdown_event = asyncio.Event()
        
    def _setup_logging(self):
        """Setup logging configuration."""
        log_level = self.config.get('logging.level', 'INFO')
        log_file = self.config.get('logging.file')
        
        # Configure root logger
        logging.basicConfig(
            level=getattr(logging, log_level),
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        
        # Add file handler if specified
        if log_file:
            try:
                import os
                os.makedirs(os.path.dirname(log_file), exist_ok=True)
                
                file_handler = logging.FileHandler(log_file)
                file_handler.setFormatter(
                    logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
                )
                logging.getLogger().addHandler(file_handler)
            except Exception as e:
                logger.warning(f"Could not setup file logging: {e}")
                
    async def initialize(self):
        """Initialize all service components."""
        logger.info("Initializing network service...")
        
        # Initialize BLE server if available
        if BLEGATTServer:
            try:
                self.ble_server = BLEGATTServer()
                logger.info("BLE GATT server initialized")
            except Exception as e:
                logger.error(f"Failed to initialize BLE server: {e}")
                self.ble_server = None
        else:
            logger.warning("BLE GATT server module not available")
            
        # Initialize network monitor
        network_config = self.config.get_network_config()
        self.network_monitor = NetworkMonitor(
            check_interval=network_config.get('check_interval', 60),
            connectivity_timeout=network_config.get('connectivity_timeout', 5),
            connectivity_hosts=network_config.get('connectivity_hosts')
        )
        
        # Initialize BLE manager
        self.ble_manager = BLEServiceManager(self.ble_server)
        
        # Set force mode from config
        force_mode = self.config.get('ble_config.force_mode', 'auto')
        if force_mode != 'auto':
            self.ble_manager.set_force_mode(force_mode)
            
        # Initialize state machine with proper configuration
        ble_config = self.config.get_ble_config()
        state_config = {
            'auto_disable': ble_config.get('auto_disable', True),
            'disable_delay': ble_config.get('disable_delay', 10),
            'connectivity_checks': ble_config.get('connectivity_checks', 3),
            'monitor_interval': ble_config.get('monitor_interval', 5),
            'reconnect_timeout': ble_config.get('reconnect_timeout', 30),
            'wifi_timeout': network_config.get('wifi_timeout', 30)
        }
        self.state_machine = NetworkStateMachine(
            network_monitor=self.network_monitor,
            ble_manager=self.ble_manager,
            config=state_config
        )
        
        logger.info("Network service initialization complete")
        
    async def start(self):
        """Start the network service."""
        if self._running:
            logger.warning("Network service already running")
            return
            
        logger.info("Starting network service...")
        self._running = True
        
        # Initialize components
        await self.initialize()
        
        # Start state machine
        await self.state_machine.start()
        
        # Setup signal handlers
        self._setup_signal_handlers()
        
        logger.info("Network service started successfully")
        
        # Wait for shutdown signal
        await self._shutdown_event.wait()
        
    async def stop(self):
        """Stop the network service."""
        if not self._running:
            return
            
        logger.info("Stopping network service...")
        self._running = False
        
        # Stop state machine
        if self.state_machine:
            await self.state_machine.stop()
            
        # Stop BLE server
        if self.ble_server:
            try:
                await self.ble_server.stop()
            except Exception as e:
                logger.error(f"Error stopping BLE server: {e}")
                
        # Set shutdown event
        self._shutdown_event.set()
        
        logger.info("Network service stopped")
        
    def _setup_signal_handlers(self):
        """Setup signal handlers for graceful shutdown."""
        def signal_handler(sig, frame):
            logger.info(f"Received signal {sig}, initiating shutdown...")
            asyncio.create_task(self.stop())
            
        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)
        
    async def get_status(self) -> dict:
        """
        Get current service status.
        
        Returns:
            Dictionary with service status information
        """
        status = {
            "running": self._running,
            "config": {
                "auto_disable": self.config.get('ble_config.auto_disable'),
                "force_mode": self.config.get('ble_config.force_mode')
            }
        }
        
        if self.state_machine:
            status["state"] = self.state_machine.get_state_info()
            
        if self.ble_manager:
            status["ble"] = self.ble_manager.get_status_info()
            
        if self.network_monitor:
            status["network"] = {
                "status": self.network_monitor.get_status().value,
                "last_check": self.network_monitor.get_last_check_time()
            }
            
        return status
        
    async def set_force_mode(self, mode: str):
        """
        Set BLE force mode.
        
        Args:
            mode: "auto", "enabled", or "disabled"
        """
        # Update configuration
        self.config.update_force_mode(mode)
        
        # Apply to state machine
        if self.state_machine:
            await self.state_machine.force_ble_mode(mode if mode != 'auto' else None)
            
        # Save configuration
        self.config.save_config()
        
        logger.info(f"Force mode set to: {mode}")
        
    async def reload_config(self):
        """Reload configuration from file."""
        self.config.reload()
        
        # Apply new configuration
        if self.state_machine:
            self.state_machine.config = self.config.get_ble_config()
            
        logger.info("Configuration reloaded")


async def main():
    """Main entry point for network service."""
    import argparse
    
    parser = argparse.ArgumentParser(description='Cloud Printer Network Service')
    parser.add_argument(
        '-c', '--config',
        help='Path to configuration file',
        default=None
    )
    parser.add_argument(
        '-d', '--debug',
        action='store_true',
        help='Enable debug logging'
    )
    
    args = parser.parse_args()
    
    # Set debug logging if requested
    if args.debug:
        logging.getLogger().setLevel(logging.DEBUG)
        
    # Create and start service
    service = NetworkService(args.config)
    
    try:
        await service.start()
    except KeyboardInterrupt:
        logger.info("Received keyboard interrupt")
    except Exception as e:
        logger.error(f"Service error: {e}")
    finally:
        await service.stop()
        

if __name__ == '__main__':
    asyncio.run(main())